﻿using log4net;
using log4net.Appender;
using log4net.Config;
using System;
using System.IO;
using System.Threading;
using System.Xml;

namespace DualReferralServer.Utils
{
    public class LogHelper
    {
        private static log4net.ILog _log = null;
        /// <summary>
        /// 日志文件过期时间(单位:天)，默认半年=180天
        /// </summary>
        private static int outdate_days = 180;

        private static object lockHelper = new object();
        private static log4net.ILog InnerLog
        {
            get
            {
                if (null == _log)
                {
                    lock (lockHelper)
                    {
                        if (null == _log)
                        {
                            try
                            {
                                string cfgfile = "log4net.config";//当前(exe文件所在)目录
                                XmlConfigurator.Configure(new System.IO.FileInfo(cfgfile));
                                _log = LogManager.GetLogger("Logging");

                                #region 删除过期的日期文件
                                Thread th = new Thread(() =>
                                {
                                    try
                                    {
                                        DeleteOutdatefiles(_log, cfgfile);
                                    }
                                    catch (Exception ex)
                                    {
                                    }
                                });
                                th.IsBackground = true;
                                th.Start();
                                #endregion
                            }
                            catch (Exception ex)
                            {
                            }
                        }
                    }
                }
                return _log;
            }
        }
        /// <summary>
        /// 删除过期的日志文件
        /// </summary>
        private static void DeleteOutdatefiles(ILog log, string cfgfile)
        {
            if (log == null ||
                !log.IsInfoEnabled ||
                !log.IsErrorEnabled)
            {
                return;
            }

            try
            {
                XmlDocument xdoc = new XmlDocument();
                xdoc.Load(cfgfile);
                var node = xdoc.SelectSingleNode("log4net");
                //附带属性到log4net.config，只能在根节点设置添加。
                //这个附带属性设置还不能放到其它节点，放到其它节点log4net解析会报错（虽未影响结果，但看着不舒服）
                if (null != node || node.Attributes != null || node.Attributes.Count > 0)
                {
                    outdate_days = int.Parse(node.Attributes["outdate_days"].Value);
                }
            }
            catch (Exception exx)
            {
            }
            var apps = log.Logger.Repository.GetAppenders();
            if (apps.Length <= 0)
            {
                return;
            }
            var now = DateTime.Now;
            foreach (var item in apps)
            {
                if (item is RollingFileAppender)
                {
                    RollingFileAppender roll = item as RollingFileAppender;
                    var dir = Path.GetDirectoryName(roll.File);
                    var files = Directory.GetFiles(dir, "*.log");
                    var sample = "log_info.log2017-10-23.log";
                    foreach (var file in files)
                    {
                        var name = Path.GetFileName(file);
                        if (name.Length != sample.Length)
                        {
                            continue;
                        }
                        var ss = name.Substring(7, 10).Split('-');
                        int year = int.Parse(ss[0]);
                        int month = int.Parse(ss[1]);
                        int day = int.Parse(ss[2]);
                        var date = new DateTime(year, month, day);
                        //TimeZone、TimeZoneInfo
                        TimeSpan ts = now - date;
                        if (ts.Days >= outdate_days)
                        {
                            try
                            {
                                File.Delete(file);
                            }
                            catch (Exception ex)
                            {
                            }
                        }
                    }
                }
            }
        }

        public static void InitLog()
        {
            ILog l = InnerLog;
        }

        public static void Debug(object message, Exception exception)
        {
            InnerLog.Debug(message, exception);
        }

        public static void Debug(object message)
        {
            InnerLog.Debug(message);
        }

        public static void DebugFormat(IFormatProvider provider, string format, params object[] args)
        {
            InnerLog.DebugFormat(provider, format, args);
        }

        public static void DebugFormat(string format, object arg0, object arg1, object arg2)
        {
            InnerLog.DebugFormat(format, arg0, arg1, arg2);
        }

        public static void DebugFormat(string format, object arg0, object arg1)
        {
            InnerLog.DebugFormat(format, arg0, arg1);
        }

        public static void DebugFormat(string format, object arg0)
        {
            InnerLog.DebugFormat(format, arg0);
        }

        public static void DebugFormat(string format, params object[] args)
        {
            InnerLog.DebugFormat(format, args);
        }

        public static void Error(object message, Exception exception)
        {
            if (InnerLog != null)
            {
                InnerLog.Error(message, exception);
            }
        }

        public static void Error(object message)
        {
            InnerLog.Error(message);
        }

        public static void ErrorFormat(IFormatProvider provider, string format, params object[] args)
        {
            InnerLog.ErrorFormat(provider, format, args);
        }

        public static void ErrorFormat(string format, object arg0, object arg1, object arg2)
        {
            InnerLog.ErrorFormat(format, arg0, arg1, arg2);
        }

        public static void ErrorFormat(string format, object arg0, object arg1)
        {
            InnerLog.ErrorFormat(format, arg0, arg1);
        }

        public static void ErrorFormat(string format, object arg0)
        {
            InnerLog.ErrorFormat(format, arg0);
        }

        public static void ErrorFormat(string format, params object[] args)
        {
            InnerLog.ErrorFormat(format, args);
        }

        public static void Fatal(object message, Exception exception)
        {
            InnerLog.Fatal(message, exception);
        }

        public static void Fatal(object message)
        {
            InnerLog.Fatal(message);
        }

        public static void FatalFormat(IFormatProvider provider, string format, params object[] args)
        {
            InnerLog.FatalFormat(provider, format, args);
        }

        public static void FatalFormat(string format, object arg0, object arg1, object arg2)
        {
            InnerLog.FatalFormat(format, arg0, arg1, arg2);
        }

        public static void FatalFormat(string format, object arg0, object arg1)
        {
            InnerLog.FatalFormat(format, arg0, arg1);
        }

        public static void FatalFormat(string format, object arg0)
        {
            InnerLog.FatalFormat(format, arg0);
        }

        public static void FatalFormat(string format, params object[] args)
        {
            InnerLog.FatalFormat(format, args);
        }

        public static void Info(object message, Exception exception)
        {
            InnerLog.Info(message, exception);
        }

        public static void Info(object message)
        {
            InnerLog.Info(message);
        }

        public static void InfoFormat(IFormatProvider provider, string format, params object[] args)
        {
            InnerLog.InfoFormat(provider, format, args);
        }

        public static void InfoFormat(string format, object arg0, object arg1, object arg2)
        {
            InnerLog.InfoFormat(format, arg0, arg1, arg2);
        }

        public static void InfoFormat(string format, object arg0, object arg1)
        {
            InnerLog.InfoFormat(format, arg0, arg1);
        }

        public static void InfoFormat(string format, object arg0)
        {
            InnerLog.InfoFormat(format, arg0);
        }

        public static void InfoFormat(string format, params object[] args)
        {
            InnerLog.InfoFormat(format, args);
        }

        public static bool IsDebugEnabled
        {
            get { return InnerLog.IsDebugEnabled; }
        }

        public static bool IsErrorEnabled
        {
            get { return InnerLog.IsErrorEnabled; }
        }

        public static bool IsFatalEnabled
        {
            get { return InnerLog.IsFatalEnabled; }
        }

        public static bool IsInfoEnabled
        {
            get { return InnerLog.IsInfoEnabled; }
        }

        public static bool IsWarnEnabled
        {
            get { return IsWarnEnabled; }
        }

        public static void Warn(object message, Exception exception)
        {
            InnerLog.Warn(message, exception);
        }

        public static void Warn(object message)
        {
            InnerLog.Warn(message);
        }

        public static void WarnFormat(IFormatProvider provider, string format, params object[] args)
        {
            InnerLog.WarnFormat(provider, format, args);
        }

        public static void WarnFormat(string format, object arg0, object arg1, object arg2)
        {
            InnerLog.WarnFormat(format, arg0, arg1, arg2);
        }

        public static void WarnFormat(string format, object arg0, object arg1)
        {
            InnerLog.WarnFormat(format, arg0, arg1);
        }

        public static void WarnFormat(string format, object arg0)
        {
            InnerLog.WarnFormat(format, arg0);
        }

        public static void WarnFormat(string format, params object[] args)
        {
            InnerLog.WarnFormat(format, args);
        }
    }
}